#!/usr/bin/env python3

import os
import re

def get_memory_info():
    """从 /proc/meminfo 获取内存信息"""
    mem_info = {}
    with open('/proc/meminfo', 'r') as f:
        for line in f:
            key, value = line.split(':', 1)
            value = value.strip().split()[0]  # 取第一个值（kB）
            mem_info[key] = int(value)
    return mem_info

def get_process_memory():
    """获取所有进程的内存使用情况（RSS）"""
    total_rss = 0  # 单位 kB
    pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
    
    for pid in pids:
        try:
            with open(f'/proc/{pid}/status', 'r') as f:
                for line in f:
                    if line.startswith('VmRSS:'):
                        rss_kb = int(line.split()[1])
                        total_rss += rss_kb
                        break
        except (FileNotFoundError, PermissionError, ProcessLookupError):
            continue  # 忽略无法访问的进程
    
    return total_rss

def calculate_memory_usage():
    """计算各种内存使用情况"""
    mem_info = get_memory_info()
    
    # 计算总内存占用（top 方式）
    total_used_kb = mem_info['MemTotal'] - mem_info['MemFree'] - mem_info['Buffers'] - mem_info['Cached']
    
    # 获取进程内存占用
    process_rss_kb = get_process_memory()
    
    # 计算内核内存组成部分（更准确的方法）
    # 这些值直接从 /proc/meminfo 获取
    kernel_stack_kb = mem_info.get('KernelStack', 0)
    page_tables_kb = mem_info.get('PageTables', 0)
    slab_kb = mem_info.get('Slab', 0)
    
    # 如果存在 SReclaimable 和 SUnreclaim，使用它们
    if 'SReclaimable' in mem_info and 'SUnreclaim' in mem_info:
        slab_kb = mem_info['SReclaimable'] + mem_info['SUnreclaim']
    
    vmalloc_used_kb = mem_info.get('VmallocUsed', 0)
    
    # 计算内核内存占用总和
    kernel_used_kb = kernel_stack_kb + page_tables_kb + slab_kb + vmalloc_used_kb
    
    # 计算用户进程内存占用（总内存占用减去内核内存）
    process_used_kb = total_used_kb - kernel_used_kb
    
    # 转换为 MiB
    total_mib = mem_info['MemTotal'] / 1024
    total_used_mib = total_used_kb / 1024
    process_used_mib = process_used_kb / 1024
    kernel_used_mib = kernel_used_kb / 1024
    
    # 计算百分比
    kernel_percent = (kernel_used_kb / mem_info['MemTotal']) * 100
    process_percent = (process_used_kb / mem_info['MemTotal']) * 100
    
    return {
        'total_mib': total_mib,
        'total_used_mib': total_used_mib,
        'process_used_mib': process_used_mib,
        'kernel_used_mib': kernel_used_mib,
        'kernel_percent': kernel_percent,
        'process_percent': process_percent,
        'mem_info': mem_info,
        'kernel_components': {
            'KernelStack': kernel_stack_kb,
            'PageTables': page_tables_kb,
            'Slab': slab_kb,
            'VmallocUsed': vmalloc_used_kb
        }
    }

def main():
    mem = calculate_memory_usage()
    
    print(f"内存使用情况概览:")
    print(f"总物理内存: {mem['total_mib']:.1f} MiB")
    print(f"总内存占用: {mem['total_used_mib']:.1f} MiB")
    print(f"用户进程内存占用: {mem['process_used_mib']:.1f} MiB ({mem['process_percent']:.1f}%)")
    print(f"内核内存占用: {mem['kernel_used_mib']:.1f} MiB ({mem['kernel_percent']:.1f}%)")
    print()
    
    print("详细内存信息 (/proc/meminfo):")
    print(f"MemTotal: {mem['mem_info']['MemTotal']} kB")
    print(f"MemFree: {mem['mem_info']['MemFree']} kB")
    print(f"Buffers: {mem['mem_info']['Buffers']} kB")
    print(f"Cached: {mem['mem_info']['Cached']} kB")
    
    # 显示内核内存组成部分
    print("\n内核内存组成部分:")
    for name, value in mem['kernel_components'].items():
        print(f"{name}: {value} kB")
    
    print(f"内核内存总计: {mem['kernel_used_mib'] * 1024:.0f} kB")

if __name__ == "__main__":
    main()